package com.authenticateCenter.service.impl;

import com.authenticateCenter.domain.entity.Authority;
import com.authenticateCenter.domain.entity.AuthorityModule;
import com.authenticateCenter.domain.entity.RoleAuthority;
import com.authenticateCenter.mapper.AuthorityMapper;
import com.authenticateCenter.mapper.AuthorityModuleMapper;
import com.authenticateCenter.mapper.RoleAuthorityMapper;
import com.authenticateCenter.service.IAuthorityModuleService;
import com.authenticateCenter.service.IAuthorityService;
import com.authenticateCenter.service.IRoleAuthorityService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 大忽悠
 * @since 2022年10月19日
 */
@Service
@Transactional
@RequiredArgsConstructor
public class AuthorityModuleServiceImpl extends ServiceImpl<AuthorityModuleMapper, AuthorityModule> implements IAuthorityModuleService {
    private final AuthorityMapper authorityMapper;
    private final RoleAuthorityMapper roleAuthorityMapper;


    /**
     * 当前资源模块下如果存在子模块需要全部删除 <br>
     * 当前资源模块下的资源也一并全部删除 <br>
     * @param authorityModuleId
     * @param iAuthorityService
     * @param iRoleAuthorityService
     */
    @Override
    public void removeAuthorityModule(Integer authorityModuleId, IAuthorityService iAuthorityService, IRoleAuthorityService iRoleAuthorityService) throws ExecutionException, InterruptedException {
        removeAuthorityModuleSeq(authorityModuleId,iAuthorityService,iRoleAuthorityService);
    }

    /**
     * 将某个资源模块赋予给某个角色,简单来说就是将该模块下管理的资源都赋予给当前角色
     */
    @Override
    public void releaseAuthorityModuleToRole(Integer roleId, Integer authorityModuleId) {
        List<Integer> idList=authorityMapper.listAuthorityIdListUnderAuthorityModuleId(authorityModuleId);
        //先回收掉权限,再进行插入,防止出现重复数据
        revokeAuthorityModuleToRole(roleId,authorityModuleId);
        idList.stream().map(aId-> RoleAuthority.builder().aid(aId).rid(roleId).build()).forEach(roleAuthorityMapper::insert);
    }

    @Override
    public void revokeAuthorityModuleToRole(Integer roleId, Integer authorityModuleId) {
        List<Integer> idList=authorityMapper.listAuthorityIdListUnderAuthorityModuleId(authorityModuleId);
        idList.forEach(aid->{
            roleAuthorityMapper.delete(new QueryWrapper<RoleAuthority>().eq("aid",aid).eq("rid",roleId));
        });
    }

    /**
     * 串行化删除方法
     *
     * @param authorityModuleId
     * @param iAuthorityService
     * @param iRoleAuthorityService
     */
    public void removeAuthorityModuleSeq(Integer authorityModuleId, IAuthorityService iAuthorityService, IRoleAuthorityService iRoleAuthorityService) {
        //1.查询出当前资源模块下所有资源,查询出来后进行删除
        deleteAuthoritiesOfCurrentAuthorityModule(authorityModuleId, iAuthorityService, iRoleAuthorityService);
        //2.查询出当前资源模块下所有子模块,递归查询,当删除完所有子模块下的资源后,再删除所有子模块,最终删除当前资源模块
        deleteSonAuthorityModuleUnderCurrentAuthorityModule(authorityModuleId, iAuthorityService, iRoleAuthorityService);
        //3.删除当前资源模块
        removeById(authorityModuleId);
    }

    /**
     * 查询出当前资源模块下所有子模块,递归查询,当删除完所有子模块下的资源后,再删除所有子模块,最终删除当前资源模块
     *
     * @param authorityModuleId
     * @param iAuthorityService
     * @param iRoleAuthorityService
     */
    private void deleteSonAuthorityModuleUnderCurrentAuthorityModule(Integer authorityModuleId, IAuthorityService iAuthorityService, IRoleAuthorityService iRoleAuthorityService) {
        List<AuthorityModule> sonAuthorityModuleList = list(new QueryWrapper<AuthorityModule>().eq("parent_id", authorityModuleId));
        //递归删除--调用串行方法
        sonAuthorityModuleList.forEach(sonAuthorityModule -> removeAuthorityModuleSeq(sonAuthorityModule.getId(), iAuthorityService, iRoleAuthorityService));
    }

    /**
     * 查询出当前资源模块下所有资源,查询出来后进行删除
     *
     * @param authorityModuleId
     * @param iAuthorityService
     * @param iRoleAuthorityService
     */
    private void deleteAuthoritiesOfCurrentAuthorityModule(Integer authorityModuleId, IAuthorityService iAuthorityService, IRoleAuthorityService iRoleAuthorityService) {
        List<Integer> authorityIdList = iAuthorityService.list(new QueryWrapper<Authority>().eq("module_id", authorityModuleId))
                .stream().map(Authority::getId).collect(Collectors.toList());
        authorityIdList.forEach(authorityId -> {
            iAuthorityService.removeAuthority(authorityId, iRoleAuthorityService);
        });
    }
}
